#include<iostream>
using namespace std;

class Shape {
public:
   Shape(int x=0, int y=0): id(uid++) {}
   virtual ~Shape() { cout<<"shape"<<id<<" is going to die"<<endl; }
   virtual void print(ostream &out=cout) const {
      out<<"shape("<<id<<") at ("<<x<<", "<<y<<")";
   }
   int getId() const { return id; }
private:
   int id;
   int x, y; //: location
   static int uid;
};
int Shape::uid=0;
ostream & operator<<(ostream &out, const Shape &s) {
   s.print(out);
   return out;
}
class Circle: public Shape {
public:
   Circle(int x=0, int y=0, int r=0): Shape(x, y), radius(r) {}
   ~Circle() { cout<<"circle"<<getId()<<" is going to die"<<endl; }
   void print(ostream &out=cout) const {
      Shape::print(out);
      out<<" radius="<<radius;
   }
private:
   int radius;
};
class Rectangle: public Shape {
public:
   Rectangle(int x=0, int y=0, int w=0, int h=0):
      Shape(x, y), width(w), height(h) {}
   void print(ostream &out=cout) const {
      Shape::print(out);
      out<<" size=("<<width<<", "<<height<<")";
   }
private:
   int width, height;
};
//================================
void testPolymorphism() {
   Shape *s1=new Circle();
   Shape *s2=new Rectangle();
   cout<<*s1<<endl<<*s2<<endl;
}
void testDestructor() {
   Shape *s1=new Circle();
   delete s1;
}
int main() {
   testPolymorphism();
   testDestructor();
   return 0;
}
